package com.mck.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mck.entity.Result;
import com.mck.interceptor.TokenInterceptor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;

@Configuration
@Slf4j
@RequiredArgsConstructor
public class SecurityConfig {

    private final TokenInterceptor tokenInterceptor; // 注入改造后的过滤器

    /**
     * 配置静态资源访问白名单
     *
     * @return WebSecurityCustomizer 实例，用于定义需要忽略安全验证的请求路径
     */
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        // 忽略静态资源和网站图标的认证检查，以及 SSE 端点
        return (web) -> web.ignoring()
                .requestMatchers("/static/**", "/favicon.ico", "/api/ai/chat-stream",
                        "/api/ai/chat-reactive");
    }

    /**
     * 配置安全过滤器链
     *
     * @param http HTTP安全配置构建器
     * @return 构建完成的安全过滤器链
     * @throws Exception 配置过程中可能抛出的异常
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 将TokenInterceptor添加到匿名认证过滤器之前
                .addFilterBefore(tokenInterceptor, AnonymousAuthenticationFilter.class)

                // 禁用CSRF保护（适用于无状态API场景）
                .csrf(AbstractHttpConfigurer::disable)
                // 配置会话管理为无状态（适用于RESTful API）
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                // 配置请求授权规则
                .authorizeHttpRequests(authorize -> authorize
                        // 放行所有OPTIONS请求
                        .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()

                        // 班级
                        .requestMatchers(HttpMethod.GET, "/api/public/classname/{classnameId}")
                        .permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/classname").permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/classname/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/classname/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.PUT, "/api/public/classname/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 当前问题
                        .requestMatchers(HttpMethod.GET, "/api/public/commonProblem")
                        .permitAll()
                        // .requestMatchers(HttpMethod.GET,
                        // "/api/public/commonProblem").hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.POST, "/api/public/commonProblem/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/commonProblem/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.PUT, "/api/public/commonProblem/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 反馈
                        .requestMatchers(HttpMethod.POST, "/api/public/feedBack/**").permitAll()
                        .requestMatchers(HttpMethod.DELETE, "/api/public/feedBack/**")
                        .permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/feedBack")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.PUT, "/api/public/feedBack/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 文件
                        .requestMatchers(HttpMethod.POST, "/api/public/file/specific")
                        .permitAll()
                        // .requestMatchers(HttpMethod.DELETE,
                        // "/api/public/file/**").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/file")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/file/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 登录
                        .requestMatchers(HttpMethod.POST, "/api/public/login").permitAll()

                        // 公告
                        .requestMatchers(HttpMethod.GET, "/api/public/notice").permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/notice")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/notice")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.PUT, "/api/public/notice")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 日志
                        .requestMatchers(HttpMethod.GET, "/api/public/operationLogs/**")
                        .permitAll()

                        // 页面
                        .requestMatchers(HttpMethod.POST, "/api/public/page").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/page")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.POST, "/api/public/page/add")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/page")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.PUT, "/api/public/page")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 成绩
                        .requestMatchers(HttpMethod.GET, "/api/public/score/radio").permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/score/specific")
                        .permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/score")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.POST, "/api/public/score")
                        .hasAnyAuthority("ROLE_2", "ROLE_5")
                        // .requestMatchers(HttpMethod.DELETE,
                        // "/api/public/score").hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 成绩统计
                        .requestMatchers(HttpMethod.POST, "/api/public/scoreStats/").permitAll()

                        // 成绩总分
                        .requestMatchers(HttpMethod.POST, "/api/public/score/total").permitAll()

                        // 科目
                        .requestMatchers(HttpMethod.GET, "/api/public/subject").permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/subject/specific")
                        .permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/subject")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/subject")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 标题
                        .requestMatchers(HttpMethod.GET, "/api/public/title").permitAll()
                        .requestMatchers(HttpMethod.PUT, "/api/public/title")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 用户班级关系
                        .requestMatchers(HttpMethod.GET, "/api/public/UserClassname/classList")
                        .permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/UserClassname/userList")
                        .hasAnyAuthority("ROLE_2", "ROLE_3", "ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.GET, "/api/public/UserClassname")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 用户
                        .requestMatchers(HttpMethod.PUT, "/api/public/users").permitAll()
                        .requestMatchers(HttpMethod.GET, "/api/public/users/specific")
                        .permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/public/users/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_2", "ROLE_5")
                        .requestMatchers(HttpMethod.DELETE, "/api/public/users/**")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers(HttpMethod.GET, "/api/public/users")
                        .hasAnyAuthority("ROLE_4", "ROLE_5")

                        // 文件上传
                        .requestMatchers(HttpMethod.GET, "/api/public/uploads/**").permitAll()

                        // 其他
                        .requestMatchers("/api/admin/**").hasAnyAuthority("ROLE_4", "ROLE_5")
                        .requestMatchers("/api/counsellor/**")
                        .hasAnyAuthority("ROLE_3", "ROLE_5")
                        .requestMatchers("/api/teacher/**").hasAnyAuthority("ROLE_2", "ROLE_5")

                        .requestMatchers("/api/public/**").authenticated()
                        .requestMatchers("/api/ai/chat").authenticated()
                        .requestMatchers("/api/ai/chat-stream").permitAll()
                        .anyRequest().authenticated())
                // 配置异常处理
                .exceptionHandling(exceptions -> exceptions
                        // 自定义权限拒绝响应（返回标准JSON格式）
                        .accessDeniedHandler((request, response, accessDeniedException) -> {
                            log.warn("Access denied for request {} by authentication: {}",
                                    request.getRequestURI(),
                                    SecurityContextHolder.getContext()
                                            .getAuthentication());

                            response.setContentType("application/json;charset=UTF-8");
                            response.setStatus(403);
                            new ObjectMapper().writeValue(
                                    response.getWriter(),
                                    Result.error("权限不足，该用户不允许访问"));
                        }));
        return http.build();
    }

    /**
     * 配置密码加密器
     *
     * @return BCrypt加密器实例，强度参数为10
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 使用BCrypt强哈希算法加密密码，强度10表示2^10次迭代
        return new BCryptPasswordEncoder(10);
    }
}
